#pragma once
#include "../common/mq_msg/mq_msg.pb.h"
#include "../common/helper.hpp"

#include <iostream>
#include <vector>

// 通配符：#匹配0个或多个单词，*匹配一个单词

namespace xzt
{
    // 用于判断routing_key和binding_key是否匹配，以及两者是否合法
    class Router    // 交换机路由管理模块
    {
    public:
        using ptr = std::shared_ptr<Router>;
    public:
        // 判断routing_key是否合法
        static bool isLegalRoutingKey(const std::string& routing_key)
        {
            // routing_key合法性判断逻辑 (合法字符：a-z, A-Z, 0-9, _, .)
            for (auto c : routing_key)
            {
                if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '.')
                {
                    continue;
                }
                return false;
            }
            return true;
        }
        // 判断binding_key是否合法
        static bool isLegalBindingKey(const std::string& binding_key)
        {
            // 1. binding_key合法性判断逻辑 (合法字符：a-z, A-Z, 0-9, _, ., #, *)
            for (auto c : binding_key)
            {
                if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '.' || c == '#' || c == '*')
                {
                    continue;
                }
                return false;
            }

            // 2. '#'和'*'必须独立存在 (一个单词中既包含其他字符，也包含通配符'#'和'*')
            std::vector<std::string> words;
            StringHelper::split(binding_key, ".", words);
            for(auto word : words)
            {
                if(word.size() > 1 && 
                   ((word.find('*') != std::string::npos || word.find('#') != std::string::npos)))
                {
                    // 说明单词中除了其他字符还包含通配符，不合法
                    return false;
                }
            }

            // 3. '#'和'*'不能连续出现 (不能再以'.'分割的两个单词中连续出现)
            // 注意：例如"a.*.*"是合法的，但是"a.#.*", "a.*.#", "a.#.#"是不合法的
            for(int i = 1; i < words.size() - 1; i++)
            {
                if(words[i] == "#" && (words[i-1] == "*" || words[i-1] == "#"))
                {
                    return false;
                }
                if(words[i] == "*" && words[i-1] == "#")
                {
                    return false;
                }
            }
            return true;
        }
        // 判断routing_key和binding_key是否匹配
        static bool route(ExchangeType type, const std::string& routing_key, const std::string& binding_key)
        {
            if(type == ExchangeType::DIRECT)    // 直连模式
            {
                return routing_key == binding_key;
            }
            else if(type == ExchangeType::FANOUT)   // 广播模式
            {
                return true;
            }
            else if(type == ExchangeType::TOPIC)    // 主题模式
            {
                // 1.先将两个key都做分割，得到两个单词列表
                std::vector<std::string> r_words, b_words;
                StringHelper::split(routing_key, ".", r_words);
                StringHelper::split(binding_key, ".", b_words);
                // 2.定义标记数组，将(0,0)位置标记为true，其他位置为false
                std::vector<std::vector<bool>> match_table(b_words.size() + 1, std::vector<bool>(r_words.size() + 1, false));
                match_table[0][0] = true;
                // 3.如果binding_key以"#"为起始，则将其对应的第0列设置为true
                for(int i = 0; i < b_words.size(); i++)
                {
                    if(b_words[i] == "#")
                    {
                        match_table[i + 1][0] = true;
                        continue;
                    }
                    break;
                }
                // 4.将routing_key中的单词与binding_key中的单词匹配，并更新match标记为true
                for(int i = 1; i <= b_words.size(); i++)
                {
                    for(int j = 1; j <= r_words.size(); j++)
                    {
                        // 如果直接匹配成功，从左上方继承结果
                        if(b_words[i-1] == r_words[j-1] || b_words[i-1] == "*")
                        {
                            match_table[i][j] = match_table[i-1][j-1];
                        }
                        else if(b_words[i-1] == "#")
                        {
                            // 如果binding_key的单词是"#"，则从左侧、上侧、左上方继承结果
                            match_table[i][j] = match_table[i-1][j] | match_table[i][j-1] | match_table[i-1][j-1];
                        }
                    }
                }
                DLOG("routing_key: {%s}, binding_key: {%s}, 匹配结果：{%d}", 
                    routing_key.c_str(), binding_key.c_str(), match_table[b_words.size()][r_words.size()]);
                return match_table[b_words.size()][r_words.size()];
            }
            else
            {
                ELOG("Router::route -> 未知的ExchangeType类型: {%d}", type);
                return false;
            }
        }

    };
}